import os, sys, math, numpy

#Se agrega al path la carpeta ../lib
modulesdir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib'))
sys.path.insert(0, modulesdir)

#Se agrega al path la carpeta ../
modulesdir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))
sys.path.insert(0, modulesdir)

from lib.euclid import Vector3
from library import *

from OpenGL.GLUT import *
from OpenGL.GL import *
from OpenGL.GLU import *

class Perspectiva(Library):
    def __init__(self, identifier, escena, parameters):
        #Asociacion de Parametros
        name = parameters[0]
        pos = parameters[1]
        zSup = parameters[2]
        zInf = parameters[3]
        tam1 = parameters[4] 
        tam2= parameters[5]
        
        self.escena = escena
        
        #Identificador
        self.identifier = identifier
        
        #Variable para que la Escena elimine el objeto de su lista de objetos, variable que indica la seleccion del objeto
        self.autoEliminate = False
        self.bSelected = False
        
        #Habilita la visualizacion del Frustum
        self.visibleFrustum = True
        
        #Tipo, nombre y colores del objeto
        self.type = 'analogia con frustum'
        self.name = name
        self.color = (0, 0, 0, 0)
        self.colorSelected = (0.5, 0.5, 0, 0)
        
        #Posicion y ancho del Frustum
        self.pos = pos
        self.width = 1
        
        #Inicializa los puntos para dibujar el Frustum
        self.zSup = zSup
        self.zInf = zInf
        self.tam1 = tam1
        self.tam2 = tam2
        self.inicialice()
        return 

    def getClassName():
        return 'Perspectiva'
    getClassName = staticmethod(getClassName)

    def getNameInMenu():
        return 'Persp'
    getNameInMenu = staticmethod(getNameInMenu)

    def getParametersForCreate():
        title = 'Este es el titulo'
        parameters = [title, 
                      ('Nombre', str), 
                      ('Posicion', float), 
                      ('Z Superior', float), 
                      ('Z Inferior', float), 
                      ('Tamano Superior', int),
                     ('Tamano Inferior', int)
                      ]
        return parameters
    getParametersForCreate = staticmethod(getParametersForCreate)

    def inicialice(self):
        '''Inicializa los Puntos de referencia del Frustum'''
        self.a = Vector3(self.pos, self.pos, self.zSup)
        self.b = Vector3(self.pos + 0.4, self.pos + 0.4, self.zSup)
        self.c = Vector3(self.pos, self.pos, self.zInf)
        
        unit = (self.b - self.a).normalized()
        #Arriba del Frustum
        unit1 = unit * self.tam1
        p1 = self.a + unit1
        p3 = self.a - unit1
        #recalculamos unit1
        unit1 = (self.a - self.c).cross(unit).normalized() * self.tam1
        p4 = self.a + unit1
        p2 = self.a - unit1
        self.points1 = [p1, p2, p3, p4, p1]
        
        #Base del Frustum
        unit2 = unit * self.tam2
        p5 = self.c + unit2
        p7 = self.c - unit2
        #recalculamos unit2
        unit2 = (self.c - self.a).cross(unit2).normalized() * self.tam2
        p6 = self.c + unit2
        p8 = self.c - unit2
        self.points2 = [p5, p6, p7, p8, p5]
        
        self.points3 = [p2, p6]
        self.points4 = [p1, p5]
        self.points5 = [p3, p7]
        self.points6 = [p4, p8]
        return


    def draw(self, selectMode=False):
        '''Callback Display del objeto'''
        if(not selectMode):
            color = self.color
            if(self.bSelected):
                color = self.colorSelected
        else:
            inc = (1.0/255)
            red = (inc) * self.identifier
            color = (red, red, red,  0)
        width = self.width
        
        if(self.visibleFrustum):
            self.drawPoligon(self.points1, color, width)
            self.drawPoligon(self.points2, color, width)
            self.drawPoligon(self.points3, color, width)
            self.drawPoligon(self.points4, color, width)
            self.drawPoligon(self.points5, color, width)
            self.drawPoligon(self.points6, color, width)
            #Punto de referencia
            origen = self.a
            radius = 0.1
            slices = 10
            stacks = 10
            self.draw_sphere(origen,  radius, slices, stacks, color)
        return 0


    def drawPoligon(self, pointsList, color, width):
        '''Dibuja un poligono con los puntos que se le pasa por parametro en forma de lista '''
        cero = pointsList[0]
        for p in pointsList:
            self.draw_line(cero, p, color, width)
            cero = p


    def Mouse(self, x, y, camara, plano):
        '''CallBack Mouse'''
        print 'mouse foto'
        return 0

    def Motion(self, x, y, width, heigth, camara, plano):
        '''CallBack Motion'''
        print 'motion foto'
        return 0

    def actionsToDo(self):
        '''Acciones del objeto'''
        verFrustum = '01-Mostrar Frustum'
        if(self.visibleFrustum):
            verFrustum = '01-Ocultar Frustum'
        self.actions = {verFrustum: (lambda x: self.setVisible(), ''), 
                        '02-Otra funcion':(lambda x:self.printAlgo('hola'), '')}
        return self.actions.keys()
    
    def printAlgo(self, cadena):
        print cadena
    
    def setVisible(self):
        '''Cambia el estado de la variable de visualizacion del Frustum'''
        self.visibleFrustum = not self.visibleFrustum
        return
    
    def atributesToEdit(self):
        '''Atributos para editar'''
        self.atributes = {'Width': (self.getWidth(), lambda spinner1:self.setWidth(spinner1))}
        return self.atributes
    
    def getWidth(self):
        return self.width

    def setWidth(self, spinbutton_widget):
        valor = round(spinbutton_widget.get_value())
        self.width = valor


